home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 January: Mac OS SDK / Dev.CD Jan 96 SDK / Dev.CD Jan 96 SDK2.toast / Development Kits (Disc 2) / QuickDraw™ 3D / Samples / SampleCode / CustomAttribute / CustomAttribute_Lib.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-11-15  |  30.1 KB  |  1,452 lines  |  [TEXT/CWIE]

  1. /*
  2.  * CustomIO_Lib.c
  3.  *
  4.  *    Demo/Template for writing custom IO functions
  5.  *    
  6.  *    Custom Attribute example
  7.  */
  8. #include <QD3D.h>
  9. #include <QD3DSet.h>
  10.  
  11. #include <QD3DIO.h>
  12. #include <QD3DString.h>
  13. #include <QD3DGeometry.h>
  14.  
  15. #include <stdlib.h>
  16.  
  17. #include "CustomAttribute_Lib.h"
  18.  
  19. /*
  20.  *    This file contains the implementation for the following custom attributes
  21.  *    
  22.  *    name - contains a string object, can be attached to any object below shape
  23.  *    scle - scale, determines the relative scale of an object/group with 1 meter
  24.  *    upvt - up vector, determines the vertical orientation of an object/group
  25.  *    fwvt - forward vector, determines the front orientation of an object/group
  26.  *    url     - allows you to attach an URL to an object/group
  27.  */
  28.  
  29. /*
  30.  * Globals
  31.  */
  32. static TQ3ObjectClass    gNameAttributeClass = NULL,
  33.                         gScaleAttributeClass = NULL,
  34.                         gUpVectorAttributeClass = NULL,
  35.                         gForwardVectorAttributeClass = NULL,
  36.                         gW3AnchorClass = NULL,
  37.                         gW3InlineClass = NULL,
  38.                         gWWWAnchorClass = NULL;
  39.  
  40.  
  41. /*
  42.  *    These are the registration calls for the individual attributes
  43.  */
  44. TQ3Status NameAttribute_Register( void);
  45.  
  46. TQ3Status NameAttribute_Unregister( void);
  47.  
  48. TQ3Status ScaleAttribute_Register( void);
  49.     
  50. TQ3Status ScaleAttribute_Unregister( void);
  51.  
  52. TQ3Status UpVectorAttribute_Register( void);
  53.  
  54. TQ3Status UpVectorAttribute_Unregister( void);
  55.  
  56. TQ3Status ForwardDirectionAttribute_Register( void);
  57.  
  58. TQ3Status ForwardDirectionAttribute_Unregister( void);
  59.  
  60. TQ3Status W3Anchor_Register( void);
  61.  
  62. TQ3Status W3Anchor_UnRegister( void);
  63.  
  64. TQ3Status W3Anchor_Unregister( void);
  65.  
  66. TQ3Status W3Inline_Register( void);
  67.  
  68. TQ3Status W3Inline_Unregister( void);
  69.  
  70. TQ3Status WWWAnchor_Register( void );
  71.  
  72. TQ3Status WWWAnchor_Unregister( void);
  73.  
  74. /**********************************************************************************************
  75.  *
  76.  *                        PUBLIC ROUTINES FOR REGISTRATION AND UNREGISTRATION
  77.  *
  78.  **********************************************************************************************/
  79.  
  80. void RegisterAllCustomAttributes(void)
  81. {
  82.     NameAttribute_Register();
  83.  
  84.     ScaleAttribute_Register();
  85.     
  86.     UpVectorAttribute_Register();
  87.  
  88.     ForwardDirectionAttribute_Register();
  89.  
  90.     W3Anchor_Register();
  91.  
  92.     W3Inline_Register();
  93.  
  94.     WWWAnchor_Register();
  95. }
  96.  
  97.  
  98. void UnregisterAllCustomAttributes(void)
  99. {
  100.     NameAttribute_Unregister();
  101.  
  102.     ScaleAttribute_Unregister();
  103.     
  104.     UpVectorAttribute_Unregister();
  105.  
  106.     ForwardDirectionAttribute_Unregister();
  107.  
  108.     W3Anchor_Unregister();
  109.  
  110.     W3Inline_Unregister();
  111.  
  112.     WWWAnchor_Unregister();
  113. }
  114.  
  115. /**********************************************************************************************
  116.  *
  117.  *                                        NAME custom attribute
  118.  *
  119.  **********************************************************************************************/
  120.  
  121.  
  122. /*
  123.  * Utility function to add a name on an shape object, geometry object, or attribute set
  124.  */
  125.  
  126. TQ3Status    SetName(TQ3Object object, char    *name)
  127. {
  128.     TQ3StringObject    string = NULL;
  129.     TQ3AttributeSet    set = NULL;
  130.     TQ3Status        status = kQ3Success;
  131.     
  132.     if( Q3Object_IsType(object, kQ3SharedTypeShape) == kQ3True ) {
  133.         
  134.         string = Q3CString_New(name);
  135.         
  136.         if( string == NULL) {
  137.             status = kQ3Failure;
  138.             goto cleanExit;
  139.         }
  140.             
  141.         if( Q3Object_IsType(object, kQ3ShapeTypeGeometry) == kQ3True ) {
  142.             
  143.             Q3Geometry_GetAttributeSet(object, &set);
  144.             
  145.             if( set == NULL ) {
  146.                 set = Q3AttributeSet_New();
  147.                 if( set == NULL ) {
  148.                     status = kQ3Failure;
  149.                     goto cleanExit;
  150.                 }
  151.                 Q3Geometry_SetAttributeSet(object, set);
  152.             }
  153.         } else {
  154.             Q3Shape_GetSet(object, &set);
  155.             
  156.             if( set == NULL ) {
  157.                 set = Q3Set_New();
  158.                 if( set == NULL ) {
  159.                     status = kQ3Failure;
  160.                     goto cleanExit;
  161.                 }
  162.                 Q3Shape_SetSet(object, set);
  163.             }
  164.         }
  165.             
  166.         if( Q3Set_Add(set, kElementTypeName, &string) == kQ3Failure ) {
  167.             status = kQ3Failure;
  168.             goto cleanExit;
  169.         }
  170.     } else if( Q3Object_IsType(object, kQ3SharedTypeSet) == kQ3True ) {
  171.         string = Q3CString_New(name);
  172.         
  173.         if( string == NULL) {
  174.             status = kQ3Failure;
  175.             goto cleanExit;
  176.         }
  177.         
  178.         if( Q3AttributeSet_Add(object, kElementTypeName, &string) == kQ3Failure ) {
  179.             status = kQ3Failure;
  180.             goto cleanExit;
  181.         }
  182.     } else 
  183.         status = kQ3Failure;
  184.         
  185. cleanExit:
  186.     if( string )
  187.         Q3Object_Dispose(string);
  188.     if( set )
  189.         Q3Object_Dispose(set);
  190.     return status;
  191. }
  192.  
  193. /*
  194.  * Static Functions
  195.  */
  196.  
  197. static TQ3Status NameAttribute_Traverse(
  198.     TQ3Object                unused,
  199.     TQ3StringObject            *stringObject,
  200.     TQ3ViewObject            view)
  201. {
  202.     (void) unused;
  203.     
  204.     if (stringObject == NULL || *stringObject == NULL)
  205.         return kQ3Success;
  206.  
  207.     Q3View_SubmitWriteData(view,0,0,0);
  208.  
  209.     if (Q3Object_Submit( *stringObject, view) == kQ3Failure)
  210.         return kQ3Failure;
  211.  
  212.     return kQ3Success;
  213. }
  214.  
  215. static TQ3Status NameAttribute_ReadData(
  216.     TQ3SetObject            attributeSet,
  217.     TQ3FileObject            file)
  218. {
  219.     TQ3StringObject        stringObject;
  220.     TQ3Status            status;
  221.     
  222.     stringObject = Q3File_ReadObject(file);
  223.         
  224.     status = Q3Set_Add(attributeSet, kElementTypeName, &stringObject);
  225.  
  226.     if (status == kQ3Failure)
  227.         Q3Object_Dispose(stringObject);
  228.  
  229.     /*
  230.         Note that the string object has a reference count of 1,
  231.         which will be taken care of in the dispose
  232.     */
  233.     return status;
  234. }
  235.  
  236. static TQ3Status NameAttribute_CopyAdd(
  237.     TQ3StringObject    *src,
  238.     TQ3StringObject    *dst)
  239. {
  240.     *dst = Q3Shared_GetReference(*src);
  241.     if (*dst == NULL) 
  242.         return kQ3Failure;
  243.     
  244.     return kQ3Success;
  245. }
  246.  
  247. static TQ3Status NameAttribute_CopyReplace(
  248.     TQ3StringObject    *src,
  249.     TQ3StringObject    *dst)
  250. {
  251.     TQ3StringObject    tempString;
  252.     
  253.     /*
  254.         It is always good form to get a reference first,
  255.         in case src and dst point to the same object
  256.     */
  257.     
  258.     tempString = Q3Shared_GetReference(*src);
  259.     if (tempString == NULL) 
  260.         return kQ3Failure;
  261.  
  262.     if( *src )
  263.         Q3Object_Dispose( *src );
  264.     
  265.     *dst = tempString;
  266.  
  267.     return kQ3Success;
  268. }
  269.  
  270. static TQ3Status NameAttribute_Delete(
  271.     TQ3StringObject    *stringObject)
  272. {
  273.     if(*stringObject)
  274.         Q3Object_Dispose(*stringObject);
  275.     return kQ3Success;
  276. }
  277.  
  278. TQ3Status NameAttribute_Unregister(
  279.     void)
  280. {
  281.     if ( gNameAttributeClass != NULL )
  282.         return    Q3ObjectClass_Unregister(gNameAttributeClass);
  283.         
  284.     return kQ3Failure;
  285. }
  286.  
  287. /*
  288.  * NameAttribute_MetaHandler
  289.  */
  290. static TQ3FunctionPointer NameAttribute_MetaHandler(
  291.     TQ3MethodType        methodType)
  292. {
  293.     switch (methodType)
  294.     {
  295.         case kQ3MethodTypeObjectTraverse:
  296.             return (TQ3FunctionPointer) NameAttribute_Traverse;
  297.         case kQ3MethodTypeObjectReadData:
  298.             return (TQ3FunctionPointer) NameAttribute_ReadData;
  299.         case kQ3MethodTypeElementCopyAdd:
  300.         case kQ3MethodTypeElementCopyGet:
  301.         case kQ3MethodTypeElementCopyDuplicate:
  302.             return (TQ3FunctionPointer) NameAttribute_CopyAdd;
  303.         case kQ3MethodTypeElementCopyReplace:
  304.             return (TQ3FunctionPointer) NameAttribute_CopyReplace;
  305.         case kQ3MethodTypeElementDelete:
  306.             return (TQ3FunctionPointer) NameAttribute_Delete;
  307.         default:
  308.             return (TQ3FunctionPointer) NULL;
  309.     }
  310. }
  311.  
  312. /*
  313.  * NameAttribute_Register
  314.  */
  315. TQ3Status NameAttribute_Register(
  316.     void)
  317. {
  318.     gNameAttributeClass = 
  319.         Q3ElementClass_Register(
  320.             kElementTypeName,
  321.             "NameAttribute",
  322.             sizeof(TQ3StringObject),
  323.             NameAttribute_MetaHandler);
  324.  
  325.     return (gNameAttributeClass == NULL ? kQ3Failure : kQ3Success);
  326. }
  327.  
  328. /**********************************************************************************************
  329.  *
  330.  *                                        SCALE custom attribute
  331.  *
  332.  **********************************************************************************************/
  333.  
  334. /*
  335.  * Utility function to add a scale on an shape object, geometry object, or attribute set
  336.  */
  337.  
  338. TQ3Status    SetScale(TQ3Object object, double scale)
  339. {
  340.     TQ3AttributeSet    set = NULL;
  341.     TQ3Status        status = kQ3Success;
  342.     
  343.     if( Q3Object_IsType(object, kQ3SharedTypeShape) == kQ3True ) {
  344.         
  345.         if( Q3Object_IsType(object, kQ3ShapeTypeGeometry) == kQ3True ) {
  346.             
  347.             Q3Geometry_GetAttributeSet(object, &set);
  348.             
  349.             if( set == NULL ) {
  350.                 set = Q3AttributeSet_New();
  351.                 if( set == NULL ) {
  352.                     status = kQ3Failure;
  353.                     goto cleanExit;
  354.                 }
  355.                 Q3Geometry_SetAttributeSet(object, set);
  356.             }
  357.         } else {
  358.             Q3Shape_GetSet(object, &set);
  359.             
  360.             if( set == NULL ) {
  361.                 set = Q3Set_New();
  362.                 if( set == NULL ) {
  363.                     status = kQ3Failure;
  364.                     goto cleanExit;
  365.                 }
  366.                 Q3Shape_SetSet(object, set);
  367.             }
  368.         }
  369.             
  370.         if( Q3Set_Add(set, kElementTypeScale, &scale) == kQ3Failure ) {
  371.             status = kQ3Failure;
  372.             goto cleanExit;
  373.         }
  374.     } else if( Q3Object_IsType(object, kQ3SharedTypeSet) == kQ3True ) {
  375.         if( Q3AttributeSet_Add(object, kElementTypeScale, &scale) == kQ3Failure ) {
  376.             status = kQ3Failure;
  377.             goto cleanExit;
  378.         }
  379.     } else 
  380.         status = kQ3Failure;
  381.         
  382. cleanExit:
  383.     if( set )
  384.         Q3Object_Dispose(set);
  385.     return status;
  386. }
  387.  
  388. /*
  389.  * ScaleAttribute_Traverse
  390.  */
  391.  
  392. static TQ3Status ScaleAttribute_Traverse(
  393.     TQ3Object                unused,
  394.     TQ3Float64                *scale,
  395.     TQ3ViewObject            view)
  396. {
  397.     (void) unused;
  398.     
  399.     if (scale == NULL)
  400.         return kQ3Success;
  401.  
  402.     return Q3View_SubmitWriteData(
  403.         view, sizeof(TQ3Float64), scale, NULL);
  404. }
  405.  
  406. /*
  407.  * ScaleAttribute_Write
  408.  */
  409.  
  410. static TQ3Status ScaleAttribute_Write(
  411.     TQ3Float64                *scale,
  412.     TQ3FileObject            file)
  413. {
  414.     return 
  415.         Q3Float64_Write(*scale, file);
  416. }
  417.  
  418. /*
  419.  * ScaleAttribute_ReadData
  420.  */
  421.  
  422. static TQ3Status ScaleAttribute_ReadData(
  423.     TQ3SetObject            attributeSet,
  424.     TQ3FileObject            file)
  425. {
  426.     double            scale;
  427.     
  428.     if( Q3Float64_Read(&scale, file) == kQ3Failure) {
  429.         return kQ3Failure;
  430.     }
  431.         
  432.     return Q3Set_Add(attributeSet, kElementTypeScale, &scale);
  433. }
  434.  
  435. /*
  436.  * ScaleAttribute_MetaHandler
  437.  */
  438. static TQ3FunctionPointer ScaleAttribute_MetaHandler(
  439.     TQ3MethodType        methodType)
  440. {
  441.     switch (methodType)
  442.     {
  443.         case kQ3MethodTypeObjectTraverse:
  444.             return (TQ3FunctionPointer) ScaleAttribute_Traverse;
  445.         case kQ3MethodTypeObjectWrite:
  446.             return (TQ3FunctionPointer) ScaleAttribute_Write;
  447.         case kQ3MethodTypeObjectReadData:
  448.             return (TQ3FunctionPointer) ScaleAttribute_ReadData;
  449.         default:
  450.             return (TQ3FunctionPointer) NULL;
  451.     }
  452. }
  453.  
  454. /*
  455.  * ScaleAttribute_Register
  456.  */
  457. TQ3Status ScaleAttribute_Register(
  458.     void)
  459. {
  460.     gScaleAttributeClass = 
  461.         Q3ElementClass_Register(
  462.             kElementTypeScale,
  463.             "ScaleAttribute",
  464.             sizeof(TQ3Float64),
  465.             ScaleAttribute_MetaHandler);
  466.  
  467.     return (gScaleAttributeClass == NULL ? kQ3Failure : kQ3Success);
  468. }
  469.  
  470. /*
  471.  * ScaleAttribute_Unregister
  472.  */
  473. TQ3Status ScaleAttribute_Unregister(
  474.     void)
  475. {
  476.     if ( gScaleAttributeClass != NULL )
  477.         return    Q3ObjectClass_Unregister(gScaleAttributeClass);
  478.         
  479.     return kQ3Failure;
  480. }
  481.  
  482. /**********************************************************************************************
  483.  *
  484.  *                                common routines for dealing with vectors
  485.  *
  486.  **********************************************************************************************/
  487.  
  488. static TQ3Status vector_Traverse(
  489.     TQ3Object                unused,
  490.     TQ3Vector3D                *upVector,
  491.     TQ3ViewObject            view)
  492. {
  493.     (void) unused;
  494.     
  495.     if (upVector == NULL)
  496.         return kQ3Success;
  497.  
  498.     return Q3View_SubmitWriteData(
  499.         view, sizeof(TQ3Vector3D), upVector, NULL);
  500. }
  501.  
  502. static TQ3Status vector_Write(
  503.     TQ3Vector3D                *upVector,
  504.     TQ3FileObject            file)
  505. {
  506.     return 
  507.         Q3Vector3D_Write(upVector, file);
  508. }
  509.  
  510. static TQ3Status vector_CopyAdd(
  511.     TQ3Vector3D    *src,
  512.     TQ3Vector3D    *dst)
  513. {
  514.     *dst = *src;
  515.     return kQ3Success;
  516. }
  517.  
  518. static TQ3Status vector_CopyReplace(
  519.     TQ3Vector3D    *src,
  520.     TQ3Vector3D    *dst)
  521. {
  522.     *dst = *src;
  523.     return kQ3Success;
  524. }
  525.  
  526. /**********************************************************************************************
  527.  *
  528.  *                                        UP VECTOR custom attribute
  529.  *
  530.  **********************************************************************************************/
  531.  
  532. /*
  533.  * Utility function to specify the up vector on a group, geometry object, or attribute set
  534.  */
  535.  
  536. TQ3Status    SetUpVector(TQ3Object object, TQ3Vector3D *upVector)
  537. {
  538.     TQ3AttributeSet    set = NULL;
  539.     TQ3Status        status = kQ3Success;
  540.     
  541.     if( Q3Object_IsType(object, kQ3ShapeTypeGeometry) == kQ3True ) {
  542.         Q3Geometry_GetAttributeSet(object, &set);
  543.         
  544.         if( set == NULL ) {
  545.             set = Q3AttributeSet_New();
  546.             if( set == NULL ) {
  547.                 status = kQ3Failure;
  548.                 goto cleanExit;
  549.             }
  550.             Q3Geometry_SetAttributeSet(object, set);
  551.         }
  552.     } else if( Q3Object_IsType(object, kQ3ShapeTypeGroup) == kQ3True ){
  553.         Q3Shape_GetSet(object, &set);
  554.         
  555.         if( set == NULL ) {
  556.             set = Q3Set_New();
  557.             if( set == NULL ) {
  558.                 status = kQ3Failure;
  559.                 goto cleanExit;
  560.             }
  561.             Q3Shape_SetSet(object, set);
  562.         }
  563.     }
  564.             
  565.     if( set ) {
  566.         if( Q3Set_Add(set, kElementTypeUpVector, &upVector) == kQ3Failure ) {
  567.             status = kQ3Failure;
  568.             goto cleanExit;
  569.         }
  570.     } else if( Q3Object_IsType(object, kQ3SharedTypeSet) == kQ3True ) {
  571.         if( Q3AttributeSet_Add(object, kElementTypeUpVector, &upVector) == kQ3Failure ) {
  572.             status = kQ3Failure;
  573.             goto cleanExit;
  574.         }
  575.     } else 
  576.         status = kQ3Failure;
  577.         
  578. cleanExit:
  579.     if( set )
  580.         Q3Object_Dispose(set);
  581.     return status;
  582. }
  583.  
  584. /*
  585.  * UpVectorAttribute_ReadData
  586.  */
  587. static TQ3Status UpVectorAttribute_ReadData(
  588.     TQ3SetObject            attributeSet,
  589.     TQ3FileObject            file)
  590. {
  591.     TQ3Vector3D        upVector;
  592.     
  593.     if( Q3Vector3D_Read(&upVector, file) == kQ3Failure) {
  594.         return kQ3Failure;
  595.     }
  596.         
  597.     return Q3Set_Add(attributeSet, kElementTypeUpVector, &upVector);
  598. }
  599.  
  600. /*
  601.  * UpVectorAttribute_MetaHandler
  602.  */
  603. static TQ3FunctionPointer UpVectorAttribute_MetaHandler(
  604.     TQ3MethodType        methodType)
  605. {
  606.     switch (methodType)
  607.     {
  608.         case kQ3MethodTypeObjectTraverse:
  609.             return (TQ3FunctionPointer) vector_Traverse;
  610.         case kQ3MethodTypeObjectWrite:
  611.             return (TQ3FunctionPointer) vector_Write;
  612.         case kQ3MethodTypeObjectReadData:
  613.             return (TQ3FunctionPointer) UpVectorAttribute_ReadData;
  614.         case kQ3MethodTypeElementCopyAdd:
  615.         case kQ3MethodTypeElementCopyGet:
  616.         case kQ3MethodTypeElementCopyDuplicate:
  617.             return (TQ3FunctionPointer) vector_CopyAdd;
  618.         case kQ3MethodTypeElementCopyReplace:
  619.             return (TQ3FunctionPointer) vector_CopyReplace;
  620.         default:
  621.             return (TQ3FunctionPointer) NULL;
  622.     }
  623. }
  624.  
  625. /*
  626.  * UpVectorAttribute_Register
  627.  */
  628. TQ3Status UpVectorAttribute_Register(
  629.     void)
  630. {
  631.     gUpVectorAttributeClass = 
  632.         Q3ElementClass_Register(
  633.             kElementTypeUpVector,
  634.             "UpVector",
  635.             sizeof(TQ3Vector3D),
  636.             UpVectorAttribute_MetaHandler);
  637.  
  638.     return (gUpVectorAttributeClass == NULL ? kQ3Failure : kQ3Success);
  639. }
  640.  
  641. /*
  642.  * UpVectorAttribute_Unregister
  643.  */
  644. TQ3Status UpVectorAttribute_Unregister(
  645.     void)
  646. {
  647.     if ( gUpVectorAttributeClass != NULL )
  648.         return    Q3ObjectClass_Unregister(gUpVectorAttributeClass);
  649.         
  650.     return kQ3Failure;
  651. }
  652.  
  653. /**********************************************************************************************
  654.  *
  655.  *                                FORWARD DIRECTION custom attribute
  656.  *
  657.  **********************************************************************************************/
  658. /*
  659.  * Utility function to add a name on a group, geometry object, or attribute set
  660.  */
  661.  
  662. TQ3Status    SetForwardDirection(TQ3Object object, TQ3Vector3D *forwardDirection)
  663. {
  664.     TQ3AttributeSet    set = NULL;
  665.     TQ3Status        status = kQ3Success;
  666.     
  667.     if( Q3Object_IsType(object, kQ3ShapeTypeGeometry) == kQ3True ) {
  668.         Q3Geometry_GetAttributeSet(object, &set);
  669.         
  670.         if( set == NULL ) {
  671.             set = Q3AttributeSet_New();
  672.             if( set == NULL ) {
  673.                 status = kQ3Failure;
  674.                 goto cleanExit;
  675.             }
  676.             Q3Geometry_SetAttributeSet(object, set);
  677.         }
  678.     } else if( Q3Object_IsType(object, kQ3ShapeTypeGroup) == kQ3True ){
  679.         Q3Shape_GetSet(object, &set);
  680.         
  681.         if( set == NULL ) {
  682.             set = Q3Set_New();
  683.             if( set == NULL ) {
  684.                 status = kQ3Failure;
  685.                 goto cleanExit;
  686.             }
  687.             Q3Shape_SetSet(object, set);
  688.         }
  689.     }
  690.             
  691.     if( set ) {
  692.         if( Q3Set_Add(set, kElementTypeForwardDirection, &forwardDirection) == kQ3Failure ) {
  693.             status = kQ3Failure;
  694.             goto cleanExit;
  695.         }
  696.     } else if( Q3Object_IsType(object, kQ3SharedTypeSet) == kQ3True ) {
  697.         if( Q3AttributeSet_Add(object, kElementTypeForwardDirection, &forwardDirection) == kQ3Failure ) {
  698.             status = kQ3Failure;
  699.             goto cleanExit;
  700.         }
  701.     } else 
  702.         status = kQ3Failure;
  703.         
  704. cleanExit:
  705.     if( set )
  706.         Q3Object_Dispose(set);
  707.     return status;
  708. }            
  709.  
  710. /*
  711.  * ForwardDirectionAttribute_ReadData
  712.  */
  713. static TQ3Status ForwardDirectionAttribute_ReadData(
  714.     TQ3SetObject            attributeSet,
  715.     TQ3FileObject            file)
  716. {
  717.     TQ3Vector3D        forwardDirection;
  718.     
  719.     if( Q3Vector3D_Read(&forwardDirection, file) == kQ3Failure) {
  720.         return kQ3Failure;
  721.     }
  722.         
  723.     return Q3Set_Add(attributeSet, kElementTypeForwardDirection, &forwardDirection);
  724. }
  725.  
  726. /*
  727.  * ForwardDirectionAttribute_MetaHandler
  728.  */
  729. static TQ3FunctionPointer ForwardDirectionAttribute_MetaHandler(
  730.     TQ3MethodType        methodType)
  731. {
  732.     switch (methodType)
  733.     {
  734.         case kQ3MethodTypeObjectTraverse:
  735.             return (TQ3FunctionPointer) vector_Traverse;
  736.         case kQ3MethodTypeObjectWrite:
  737.             return (TQ3FunctionPointer) vector_Write;
  738.         case kQ3MethodTypeObjectReadData:
  739.             return (TQ3FunctionPointer) ForwardDirectionAttribute_ReadData;
  740.         default:
  741.             return (TQ3FunctionPointer) NULL;
  742.     }
  743. }
  744.  
  745. /*
  746.  * ForwardDirectionAttribute_Register
  747.  */
  748. TQ3Status ForwardDirectionAttribute_Register(
  749.     void)
  750. {
  751.     gUpVectorAttributeClass = 
  752.         Q3ElementClass_Register(
  753.             kElementTypeForwardDirection,
  754.             "ForwardDirection",
  755.             sizeof(TQ3Vector3D),
  756.             ForwardDirectionAttribute_MetaHandler);
  757.  
  758.     return (gForwardVectorAttributeClass == NULL ? kQ3Failure : kQ3Success);
  759. }
  760.  
  761. /*
  762.  * ForwardDirectionAttribute_Unregister
  763.  */
  764. TQ3Status ForwardDirectionAttribute_Unregister(
  765.     void)
  766. {
  767.     if ( gForwardVectorAttributeClass != NULL )
  768.         return    Q3ObjectClass_Unregister(gForwardVectorAttributeClass);
  769.         
  770.     return kQ3Failure;
  771. }
  772.  
  773. /***********************************************************************************************
  774. *
  775. *    W3Anchor - This allows you attach an URL (universal resource locator) to an object or
  776. *    group.  If this attribute is attached to a group, it should be interpreted as applying
  777. *    to all the objects inside the group.
  778. *
  779. *
  780. ***********************************************************************************************/
  781.  
  782. /*
  783.  * Utility function to attach an URL reference to a group object, geometry object, or attribute set
  784.  */
  785.  
  786. TQ3Status    SetW3Anchor(TQ3Object object, char *url, char *description, W3AnchorOptions options)
  787. {
  788.     TQ3StringObject        string = NULL;
  789.     TQ3AttributeSet        set = NULL;
  790.     TQ3Status            status = kQ3Success;
  791.     W3AnchorData        W3Anchor;
  792.         
  793.     string = Q3CString_New(description);
  794.     
  795.     if( string == NULL) {
  796.         status = kQ3Failure;
  797.         goto cleanExit;
  798.     }
  799.     
  800.     W3Anchor.description = string;
  801.     W3Anchor.url = url;
  802.     W3Anchor.options = options;
  803.     
  804.     if( Q3Object_IsType(object, kQ3ShapeTypeGeometry) == kQ3True ) {
  805.         
  806.         Q3Geometry_GetAttributeSet(object, &set);
  807.         
  808.         if( set == NULL ) {
  809.             set = Q3AttributeSet_New();
  810.             if( set == NULL ) {
  811.                 status = kQ3Failure;
  812.                 goto cleanExit;
  813.             }
  814.             Q3Geometry_SetAttributeSet(object, set);
  815.         }
  816.     } else if( Q3Object_IsType(object, kQ3ShapeTypeGroup) == kQ3True ) {
  817.         Q3Shape_GetSet(object, &set);
  818.         
  819.         if( set == NULL ) {
  820.             set = Q3Set_New();
  821.             if( set == NULL ) {
  822.                 status = kQ3Failure;
  823.                 goto cleanExit;
  824.             }
  825.             Q3Shape_SetSet(object, set);
  826.         }
  827.     }
  828.     
  829.     if( set ) {        
  830.         if( Q3Set_Add(set, kElementTypeW3Anchor, &W3Anchor) == kQ3Failure ) {
  831.             status = kQ3Failure;
  832.             goto cleanExit;
  833.         }
  834.     } else if( Q3Object_IsType(object, kQ3SharedTypeSet) == kQ3True ) {
  835.         if( Q3AttributeSet_Add(object, kElementTypeW3Anchor, &W3Anchor) == kQ3Failure ) {
  836.             status = kQ3Failure;
  837.             goto cleanExit;
  838.         }
  839.     } else 
  840.         status = kQ3Failure;
  841.         
  842. cleanExit:
  843.     if( set )
  844.         Q3Object_Dispose(set);
  845.     if( string )
  846.         Q3Object_Dispose(string);
  847.     return status;
  848. }
  849.  
  850.  
  851. /*
  852.  * W3Anchor_Traverse
  853.  */
  854. static TQ3Status W3Anchor_Traverse(
  855.     W3AnchorData            *URLdata,
  856.     TQ3FileObject            file)
  857. {
  858.     TQ3Size        size;
  859.     
  860.     if (URLdata->url == NULL)
  861.         return kQ3Success;
  862.     
  863.     size = Q3Size_Pad(strlen(URLdata->url)) + 1;
  864.     size += sizeof(TQ3Uns32);
  865.     
  866.     if( Q3View_SubmitWriteData(file, size, URLdata, NULL) == kQ3Failure )
  867.         return kQ3Failure;
  868.     
  869.     if(URLdata->description) {
  870.         if( Q3Object_Submit(URLdata->description, file) == kQ3Failure )
  871.             return kQ3Failure;
  872.     }
  873.     
  874.     return kQ3Success;
  875. }
  876.  
  877. /*
  878.  * W3Anchor_Write
  879.  */
  880. static TQ3Status W3Anchor_Write(
  881.     W3AnchorData            *URLdata,
  882.     TQ3FileObject            file)
  883. {
  884.     return 
  885.         Q3String_Write(URLdata->url, file) == kQ3Success &&
  886.         Q3Uns32_Write((unsigned long) URLdata->options, file) == kQ3Success ? kQ3Success : kQ3Failure;
  887. }
  888.  
  889. /*
  890.  * W3Anchor_ReadData
  891.  */
  892. static TQ3Status W3Anchor_ReadData(
  893.     TQ3SetObject            set,
  894.     TQ3FileObject            file)
  895. {
  896.     char                buf[kQ3StringMaximumLength];
  897.     W3AnchorData        URLData = {NULL, NULL, kW3AnchorOptionNone};
  898.     
  899.     if (Q3String_Read(buf, NULL, file) == kQ3Failure)
  900.         return kQ3Failure;
  901.  
  902.     URLData.url = malloc( strlen(buf) + 1);
  903.     strcpy( URLData.url, buf);
  904.     
  905.     if (Q3Uns32_Read( (unsigned long *) &URLData.options, file) == kQ3Failure)
  906.         return kQ3Failure;
  907.     
  908.     if( Q3File_IsEndOfContainer(file, NULL) == kQ3False ) {
  909.         URLData.description = Q3File_ReadObject(file);
  910.     }
  911.     
  912.     return Q3Set_Add(set, kElementTypeW3Anchor, &URLData);
  913. }
  914.  
  915. /*
  916.  * W3Anchor_CopyAdd
  917.  */
  918. static TQ3Status W3Anchor_CopyAdd(
  919.     W3AnchorData    *src,
  920.     W3AnchorData    *dst)
  921. {
  922.     long    i;
  923.     
  924.     if (src->url == NULL)
  925.         return kQ3Failure;
  926.  
  927.     i = strlen(src->url);
  928.     
  929.     if (i == 0)
  930.         return kQ3Failure;
  931.     
  932.     dst->url = malloc(i + 1);
  933.     
  934.     if (dst->url == NULL)
  935.         return kQ3Failure;
  936.         
  937.     strcpy(dst->url, src->url);
  938.     
  939.     if( src->description ) {
  940.         TQ3StringObject    stringReference;
  941.         
  942.         stringReference = Q3Shared_GetReference(src->description);
  943.         
  944.         if( stringReference == NULL) {
  945.             return kQ3Failure;
  946.         }
  947.         
  948.         dst->description = stringReference;
  949.     } else
  950.         dst->description = NULL;
  951.         
  952.     dst->options = src->options;
  953.     return kQ3Success;
  954. }
  955.  
  956. /*
  957.  * W3Anchor_CopyReplace
  958.  */
  959. static TQ3Status W3Anchor_CopyReplace(
  960.     W3AnchorData    *src,
  961.     W3AnchorData    *dst)
  962. {
  963.     long    i;
  964.     char    *c;
  965.     
  966.     if (src->url == NULL)
  967.         return kQ3Failure;
  968.  
  969.     i = strlen(src->url);
  970.     
  971.     if (i == 0)
  972.         return kQ3Failure;
  973.         
  974.     c = realloc(dst->url, i + 1);
  975.     
  976.     if (c == NULL)
  977.         return kQ3Failure;
  978.     
  979.     dst->url = c;
  980.         
  981.     strcpy(dst->url, src->url);
  982.     
  983.     if( src->description ) {
  984.         TQ3StringObject    stringReference;
  985.         
  986.         stringReference = Q3Shared_GetReference(src->description);
  987.         
  988.         if( stringReference == NULL) {
  989.             return kQ3Failure;
  990.         }
  991.         
  992.         if( dst->description ) {
  993.             Q3Object_Dispose(dst->description);
  994.         }
  995.         
  996.         dst->description = stringReference;
  997.     } else
  998.         dst->description = NULL;
  999.         
  1000.     dst->options = src->options;
  1001.     return kQ3Success;
  1002. }
  1003.  
  1004. /*
  1005.  * W3Anchor_Delete
  1006.  */
  1007. static TQ3Status W3Anchor_Delete(
  1008.     W3AnchorData    *URLData)
  1009. {
  1010.     if (URLData->url != NULL) 
  1011.         free(URLData->url);
  1012.  
  1013.     if (URLData->description != NULL) 
  1014.         Q3Object_Dispose(URLData->description);
  1015.  
  1016.     return kQ3Success;
  1017. }
  1018.  
  1019. /*
  1020.  * W3Anchor_MetaHandler
  1021.  */
  1022. static TQ3FunctionPointer W3Anchor_MetaHandler(
  1023.     TQ3MethodType        methodType)
  1024. {
  1025.     switch (methodType)
  1026.     {
  1027.         case kQ3MethodTypeObjectTraverse:
  1028.             return (TQ3FunctionPointer) W3Anchor_Traverse;
  1029.         case kQ3MethodTypeObjectWrite:
  1030.             return (TQ3FunctionPointer) W3Anchor_Write;
  1031.         case kQ3MethodTypeObjectReadData:
  1032.             return (TQ3FunctionPointer) W3Anchor_ReadData;
  1033.         case kQ3MethodTypeElementCopyAdd:
  1034.         case kQ3MethodTypeElementCopyGet:
  1035.         case kQ3MethodTypeElementCopyDuplicate:
  1036.             return (TQ3FunctionPointer) W3Anchor_CopyAdd;
  1037.         case kQ3MethodTypeElementCopyReplace:
  1038.             return (TQ3FunctionPointer) W3Anchor_CopyReplace;
  1039.         case kQ3MethodTypeElementDelete:
  1040.             return (TQ3FunctionPointer) W3Anchor_Delete;
  1041.         default:
  1042.             return (TQ3FunctionPointer) NULL;
  1043.     }
  1044. }
  1045.  
  1046. /*
  1047.  * W3Anchor_Register
  1048.  */
  1049. TQ3Status W3Anchor_Register(
  1050.     void)
  1051. {
  1052.     gW3AnchorClass = 
  1053.         Q3ElementClass_Register(
  1054.             kElementTypeW3Anchor,
  1055.             "W3Anchor",
  1056.             sizeof(W3AnchorData),
  1057.             W3Anchor_MetaHandler);
  1058.  
  1059.     return (gW3AnchorClass == NULL ? kQ3Failure : kQ3Success);
  1060. }
  1061.  
  1062. TQ3Status W3Anchor_Unregister(
  1063.     void)
  1064. {
  1065.     if(gW3AnchorClass)
  1066.         return Q3ObjectClass_Unregister(gW3AnchorClass);
  1067.     else
  1068.         return kQ3Success;
  1069. }
  1070.  
  1071. /***********************************************************************************************
  1072. *
  1073. *    W3Inline - Attach this to a proxy group or geometry
  1074. *
  1075. *
  1076. ***********************************************************************************************/
  1077.  
  1078. /*
  1079.  * Utility function to add a name on a group object, geometry object, or attribute set
  1080.  */
  1081.  
  1082. TQ3Status    SetW3Inline(TQ3Object object, char *url)
  1083. {
  1084.     TQ3AttributeSet        set = NULL;
  1085.     TQ3Status            status = kQ3Success;
  1086.     W3InlineData        W3Inline;
  1087.     
  1088.     W3Inline.url = url;
  1089.  
  1090.     if( Q3Object_IsType(object, kQ3ShapeTypeGeometry) == kQ3True ) {
  1091.         Q3Geometry_GetAttributeSet(object, &set);
  1092.         
  1093.         if( set == NULL ) {
  1094.             set = Q3AttributeSet_New();
  1095.             if( set == NULL ) {
  1096.                 status = kQ3Failure;
  1097.                 goto cleanExit;
  1098.             }
  1099.             Q3Geometry_SetAttributeSet(object, set);
  1100.         }
  1101.     } else     if( Q3Object_IsType(object, kQ3ShapeTypeGroup ) == kQ3True ) {
  1102.         Q3Shape_GetSet(object, &set);
  1103.         
  1104.         if( set == NULL ) {
  1105.             set = Q3Set_New();
  1106.             if( set == NULL ) {
  1107.                 status = kQ3Failure;
  1108.                 goto cleanExit;
  1109.             }
  1110.             Q3Shape_SetSet(object, set);
  1111.         }
  1112.     }
  1113.         
  1114.     if( set ) {    
  1115.         if( Q3Set_Add(set, kElementTypeW3Inline, &W3Inline) == kQ3Failure ) {
  1116.             status = kQ3Failure;
  1117.             goto cleanExit;
  1118.         }
  1119.     } else if( Q3Object_IsType(object, kQ3SharedTypeSet) == kQ3True ) {
  1120.         if( Q3AttributeSet_Add(object, kElementTypeW3Inline, &W3Inline) == kQ3Failure ) {
  1121.             status = kQ3Failure;
  1122.             goto cleanExit;
  1123.         }
  1124.     } else 
  1125.         status = kQ3Failure;
  1126.         
  1127. cleanExit:
  1128.     if( set )
  1129.         Q3Object_Dispose(set);
  1130.     return status;
  1131. }
  1132.  
  1133. /*
  1134.  * Static Functions
  1135.  */
  1136. static TQ3Status W3Inline_Traverse(
  1137.     W3InlineData            *inlineData,
  1138.     TQ3FileObject            file)
  1139. {
  1140.     TQ3Size        size;
  1141.     
  1142.     if (inlineData->url == NULL)
  1143.         return kQ3Success;
  1144.     
  1145.     size = Q3Size_Pad(strlen(inlineData->url) + 1);
  1146.     
  1147.     return
  1148.         Q3View_SubmitWriteData(file, size, inlineData, NULL);
  1149. }
  1150.  
  1151. static TQ3Status W3Inline_Write(
  1152.     W3InlineData            *inlineData,
  1153.     TQ3FileObject            file)
  1154. {
  1155.     return 
  1156.         Q3String_Write(inlineData->url, file) == kQ3Success &&
  1157.         Q3Comment_Write("url", file) == kQ3Success ? kQ3Success : kQ3Failure;
  1158. }
  1159.  
  1160. static TQ3Status W3Inline_ReadData(
  1161.     TQ3SetObject            set,
  1162.     TQ3FileObject            file)
  1163. {
  1164.     char                buf[kQ3StringMaximumLength];
  1165.     W3InlineData        inlineData;
  1166.     
  1167.     if (Q3String_Read(buf, NULL, file) == kQ3Failure)
  1168.         return kQ3Failure;
  1169.  
  1170.     inlineData.url = buf;
  1171.     
  1172.     return Q3Set_Add(set, kElementTypeW3Inline, &inlineData);
  1173. }
  1174.  
  1175. static TQ3Status W3Inline_CopyAdd(
  1176.     W3InlineData    *src,
  1177.     W3InlineData    *dst)
  1178. {
  1179.     long    i;
  1180.     
  1181.     if (src->url == NULL)
  1182.         return kQ3Failure;
  1183.  
  1184.     i = strlen(src->url);
  1185.     
  1186.     if (i == 0)
  1187.         return kQ3Failure;
  1188.         
  1189.     dst->url = malloc(i + 1);
  1190.     
  1191.     if (dst->url == NULL)
  1192.         return kQ3Failure;
  1193.         
  1194.     strcpy(dst->url, src->url);
  1195.     
  1196.     return kQ3Success;
  1197. }
  1198.  
  1199. static TQ3Status W3Inline_CopyReplace(
  1200.     W3InlineData    *src,
  1201.     W3InlineData    *dst)
  1202. {
  1203.     long    i;
  1204.     char    *c;
  1205.     
  1206.     if (src->url == NULL)
  1207.         return kQ3Failure;
  1208.  
  1209.     i = strlen(src->url);
  1210.     
  1211.     if (i == 0)
  1212.         return kQ3Failure;
  1213.         
  1214.     c = realloc(dst->url, i + 1);
  1215.     
  1216.     if (c == NULL)
  1217.         return kQ3Failure;
  1218.     
  1219.     dst->url = c;
  1220.         
  1221.     strcpy(dst->url, src->url);
  1222.     
  1223.     return kQ3Success;
  1224. }
  1225.  
  1226. static TQ3Status W3Inline_Delete(
  1227.     W3InlineData    *src)
  1228. {
  1229.     if (src->url != NULL) 
  1230.         free(src->url);
  1231.  
  1232.     return kQ3Success;
  1233. }
  1234.  
  1235. /*
  1236.  * W3Inline_MetaHandler
  1237.  */
  1238. static TQ3FunctionPointer W3Inline_MetaHandler(
  1239.     TQ3MethodType        methodType)
  1240. {
  1241.     switch (methodType)
  1242.     {
  1243.         case kQ3MethodTypeObjectTraverse:
  1244.             return (TQ3FunctionPointer) W3Inline_Traverse;
  1245.         case kQ3MethodTypeObjectWrite:
  1246.             return (TQ3FunctionPointer) W3Inline_Write;
  1247.         case kQ3MethodTypeObjectReadData:
  1248.             return (TQ3FunctionPointer) W3Inline_ReadData;
  1249.         case kQ3MethodTypeElementCopyAdd:
  1250.         case kQ3MethodTypeElementCopyGet:
  1251.         case kQ3MethodTypeElementCopyDuplicate:
  1252.             return (TQ3FunctionPointer) W3Inline_CopyAdd;
  1253.         case kQ3MethodTypeElementCopyReplace:
  1254.             return (TQ3FunctionPointer) W3Inline_CopyReplace;
  1255.         case kQ3MethodTypeElementDelete:
  1256.             return (TQ3FunctionPointer) W3Inline_Delete;
  1257.         default:
  1258.             return (TQ3FunctionPointer) NULL;
  1259.     }
  1260. }
  1261.  
  1262. /*
  1263.  * W3Inline_Register
  1264.  */
  1265. TQ3Status W3Inline_Register(
  1266.     void)
  1267. {
  1268.     gW3InlineClass = 
  1269.         Q3ElementClass_Register(
  1270.             kElementTypeW3Inline,
  1271.             "W3Inline",
  1272.             sizeof(W3InlineData),
  1273.             W3Inline_MetaHandler);
  1274.  
  1275.     return (gW3InlineClass == NULL ? kQ3Failure : kQ3Success);
  1276. }
  1277.  
  1278. TQ3Status W3Inline_Unregister(
  1279.     void)
  1280. {
  1281.     return Q3ObjectClass_Unregister(gW3InlineClass);
  1282. }
  1283.  
  1284.  
  1285. /***********************************************************************************************
  1286. *
  1287. *    This one is obsolete.  The code below will convert to the new type on reading and writing
  1288. *
  1289. *
  1290. ***********************************************************************************************/
  1291.  
  1292. /*
  1293.  * Static Functions
  1294.  */
  1295. static TQ3Status WWWAnchor_Traverse(
  1296.     WWWAnchorData            *wwwdata,
  1297.     TQ3FileObject            file)
  1298. {
  1299.     TQ3Size        size;
  1300.     
  1301.     if (wwwdata->url == NULL)
  1302.         return kQ3Success;
  1303.     
  1304.     size = Q3Size_Pad(strlen(wwwdata->url) + 1);
  1305.     
  1306.     return
  1307.         Q3View_SubmitWriteData(file, size, wwwdata, NULL);
  1308. }
  1309.  
  1310. static TQ3Status WWWAnchor_Write(
  1311.     WWWAnchorData            *wwwdata,
  1312.     TQ3FileObject            file)
  1313. {
  1314.     return 
  1315.         Q3String_Write(wwwdata->url, file) == kQ3Success &&
  1316.         Q3Comment_Write("url", file) == kQ3Success ? kQ3Success : kQ3Failure;
  1317. }
  1318.  
  1319. static TQ3Status WWWAnchor_ReadData(
  1320.     TQ3SetObject            set,
  1321.     TQ3FileObject            file)
  1322. {
  1323.     char                buf[kQ3StringMaximumLength];
  1324.     WWWAnchorData        wwwdata;
  1325.     W3AnchorData        W3Anchor;
  1326.     
  1327.     if (Q3String_Read(buf, NULL, file) == kQ3Failure)
  1328.         return kQ3Failure;
  1329.  
  1330.     wwwdata.url = malloc(strlen(buf) + 1);
  1331.     strcpy(wwwdata.url, buf);
  1332.  
  1333.     W3Anchor.url = malloc(strlen(buf) + 1);
  1334.     strcpy(W3Anchor.url, buf);
  1335.      
  1336.      W3Anchor.description = NULL;
  1337.      W3Anchor.options = kW3AnchorOptionNone;
  1338.      
  1339.      Q3Set_Add(set, kElementTypeW3Anchor, &W3Anchor);
  1340.      
  1341.     return Q3Set_Add(set, kElementTypeWWWAnchor, &wwwdata);
  1342. }
  1343.  
  1344. static TQ3Status WWWAnchor_CopyAdd(
  1345.     WWWAnchorData    *src,
  1346.     WWWAnchorData    *dst)
  1347. {
  1348.     long    i;
  1349.     
  1350.     if (src->url == NULL)
  1351.         return kQ3Failure;
  1352.  
  1353.     i = strlen(src->url);
  1354.     
  1355.     if (i == 0)
  1356.         return kQ3Failure;
  1357.         
  1358.     dst->url = malloc(i + 1);
  1359.     
  1360.     if (dst->url == NULL)
  1361.         return kQ3Failure;
  1362.         
  1363.     strcpy(dst->url, src->url);
  1364.     
  1365.     return kQ3Success;
  1366. }
  1367.  
  1368. static TQ3Status WWWAnchor_CopyReplace(
  1369.     WWWAnchorData    *src,
  1370.     WWWAnchorData    *dst)
  1371. {
  1372.     long    i;
  1373.     char    *c;
  1374.     
  1375.     if (src->url == NULL)
  1376.         return kQ3Failure;
  1377.  
  1378.     i = strlen(src->url);
  1379.     
  1380.     if (i == 0)
  1381.         return kQ3Failure;
  1382.         
  1383.     c = realloc(dst->url, i + 1);
  1384.     
  1385.     if (c == NULL)
  1386.         return kQ3Failure;
  1387.     
  1388.     dst->url = c;
  1389.         
  1390.     strcpy(dst->url, src->url);
  1391.     
  1392.     return kQ3Success;
  1393. }
  1394.  
  1395. static TQ3Status WWWAnchor_Delete(
  1396.     WWWAnchorData    *src)
  1397. {
  1398.     if (src->url != NULL) 
  1399.         free(src->url);
  1400.  
  1401.     return kQ3Success;
  1402. }
  1403.  
  1404. /*
  1405.  * WWWAnchor_MetaHandler
  1406.  */
  1407. static TQ3FunctionPointer WWWAnchor_MetaHandler(
  1408.     TQ3MethodType        methodType)
  1409. {
  1410.     switch (methodType)
  1411.     {
  1412.         case kQ3MethodTypeObjectTraverse:
  1413.             return (TQ3FunctionPointer) WWWAnchor_Traverse;
  1414.         case kQ3MethodTypeObjectWrite:
  1415.             return (TQ3FunctionPointer) WWWAnchor_Write;
  1416.         case kQ3MethodTypeObjectReadData:
  1417.             return (TQ3FunctionPointer) WWWAnchor_ReadData;
  1418.         case kQ3MethodTypeElementCopyAdd:
  1419.         case kQ3MethodTypeElementCopyGet:
  1420.         case kQ3MethodTypeElementCopyDuplicate:
  1421.             return (TQ3FunctionPointer) WWWAnchor_CopyAdd;
  1422.         case kQ3MethodTypeElementCopyReplace:
  1423.             return (TQ3FunctionPointer) WWWAnchor_CopyReplace;
  1424.         case kQ3MethodTypeElementDelete:
  1425.             return (TQ3FunctionPointer) WWWAnchor_Delete;
  1426.         default:
  1427.             return (TQ3FunctionPointer) NULL;
  1428.     }
  1429. }
  1430.  
  1431. /*
  1432.  * WWWAnchor_Register
  1433.  */
  1434. TQ3Status WWWAnchor_Register(
  1435.     void)
  1436. {
  1437.     gWWWAnchorClass = 
  1438.         Q3ElementClass_Register(
  1439.             kElementTypeWWWAnchor,
  1440.             kElementNameWWWAnchor,
  1441.             sizeof(WWWAnchorData),
  1442.             WWWAnchor_MetaHandler);
  1443.  
  1444.     return (gWWWAnchorClass == NULL ? kQ3Failure : kQ3Success);
  1445. }
  1446.  
  1447. TQ3Status WWWAnchor_Unregister(
  1448.     void)
  1449. {
  1450.     return Q3ObjectClass_Unregister(gWWWAnchorClass);
  1451. }
  1452.